//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<loop_scheduler.h>
///	@path	~/src/engine/xcore/
///	@date	2008/03/20
///	@desc	.

#pragma once

#include "xeres.h"

#include "lib/utilities/dep_stages.h"
#include "lib/system/signal.h"
#include "lib/system/thread.h"

#include "engine/xcore/tick_scheduler.h"
#include "engine/xcore/render_scheduler.h"
#include "engine/xcore/task_manager.h"

namespace xeres {

	/*! 
		\class	LoopScheduler
		\brief	Tick loop scheduler.
	*/
	class LoopScheduler : public TickScheduler , public RenderScheduler , public TaskManager
	{
	protected:

		/// \name Constructor & Destructor
		//@{

		/// \ctor
		LoopScheduler( void );

		/// \dtor
		~LoopScheduler( void );

		//@}

		/// \name Internal Manipulation
		//@{

		/*! 
			\brief		First frame start up.
		*/
		void FirstFrame( void );

		/*! 
			\brief		Last frame clean up.
		*/
		void LastFrame( void );

		/*!
			\brief		Perform next frame update.
		*/
		void UpdateFrame( void );

		/*!
			\brief		Set tick loop parallelized.
						This function must be called before the first UpdateFrame.
		*/
		bool SetTickParallelized( void );

		/*!
			\brief		Set render loop parallelized.
						This function must be called before the first UpdateFrame.
		*/
		bool SetRenderParallelized( void );

		/*!
			\brief		Creates dispatching job pool.
		*/
		void ConfigMultiTasking( const WString& strategy , int thread_count , bool config_affinity );

		//@}

	public:

		/// \name	Loop Controls
		//@{

		/*!
			\brief		Determine if engine is running in parallel update.
						Parallel update means UpdateFrame and Render runs at the same time.
						UpdateFrame and Render will run on different thread.
		*/
		bool IsParallel( void ) const { return m_parallelize != 0; }

		//@}

	private:

		/// \name Internal Method
		//@{

		/*! 
			\brief		Tick wrap.
		*/
		void DoTick( void );

		/*!
			\brief		Render wrap.
		*/
		void DoRender( void );

		/*!
			\brief		Thread procedure to run render screen.
		*/
		void RenderThread( void );

		/*!
			\brief		Thread procedure to run tick.
		*/
		void TickThread( void );

		/*!
			\brief		Parallelized run tick. (With render in main thread, DX9 must use!)
		*/
		void ParallelTick( void );

		/*!
			\brief		Parallelized run render.
		*/
		void ParallelRender( void );

		//@}

		//@ data

		Signal				m_loopSignal;
		Signal				m_loopSyncSignal;
		ProcThread *		m_loopThread;

		int					m_parallelize; // game loop is parallelized

	};

} // namespace xeres
